#include "utils/utils/string_cast.h"
#include <cerrno>
#include <climits>
#include <cstring>

namespace base::utils
{
StringCast::StringCast()
{

}
int StringCast::toInt(const std::string &str, bool *ok, int base)
{
    errno = 0;//EDOM/ERANGE/EILSEQ
    char *pEnd;
    auto result = strtol(str.c_str(), &pEnd, base);
    if (strncmp(pEnd, "\0", 1) != 0 || errno != 0 || result > INT_MAX)
    {
        result = 0;
        if (ok)
        { *ok = false; }
    }
    else
    {
        if (ok)
        { *ok = true; }
    }
    return (int) result;
}
long long StringCast::toLongLong(const std::string &str, bool *ok, int base)
{
    errno = 0;//EDOM/ERANGE/EILSEQ
    char *pEnd;
    auto result = strtoll(str.c_str(), &pEnd, base);
    if (strncmp(pEnd, "\0", 1) != 0 || errno != 0 || result > LLONG_MAX)
    {
        result = 0;
        if (ok)
        { *ok = false; }
    }
    else
    {
        if (ok)
        { *ok = true; }
    }
    return result;
}
unsigned int StringCast::toUInt(const std::string &str, bool *ok, int base)
{
    errno = 0;//EDOM/ERANGE/EILSEQ
    char *pEnd;
    auto result = strtoul(str.c_str(), &pEnd, base);
    if (strncmp(pEnd, "\0", 1) != 0 || errno != 0 || result > UINT_MAX)
    {
        result = 0;
        if (ok)
        { *ok = false; }
    }
    else
    {
        if (ok)
        { *ok = true; }
    }
    return (unsigned int) result;
}
unsigned long long StringCast::toULongLong(const std::string &str, bool *ok, int base)
{
    errno = 0;//EDOM/ERANGE/EILSEQ
    char *pEnd;
    auto result = strtoull(str.c_str(), &pEnd, base);
    if (strncmp(pEnd, "\0", 1) != 0 || errno != 0 || result > ULLONG_MAX)
    {
        result = 0;
        if (ok)
        { *ok = false; }
    }
    else
    {
        if (ok)
        { *ok = true; }
    }
    return result;
}
double StringCast::toDouble(const std::string &str, bool *ok)
{
    errno = 0;//EDOM/ERANGE/EILSEQ
    char *pEnd;
    auto result = strtod(str.c_str(), &pEnd);
    if (strncmp(pEnd, "\0", 1) != 0 || errno != 0)
    {
        result = 0.0;
        if (ok)
        { *ok = false; }
    }
    else
    {
        if (ok)
        { *ok = true; }
    }
    return result;
}
long double StringCast::toLongDouble(const std::string &str, bool *ok)
{
    errno = 0;//EDOM/ERANGE/EILSEQ
    char *pEnd;
    auto result = strtold(str.c_str(), &pEnd);
    if (strncmp(pEnd, "\0", 1) != 0 || errno != 0)
    {
        result = 0.0;
        if (ok)
        { *ok = false; }
    }
    else
    {
        if (ok)
        { *ok = true; }
    }
    return result;
}
float StringCast::toFloat(const std::string &str, bool *ok)
{
    errno = 0;//EDOM/ERANGE/EILSEQ
    char *pEnd;
    auto result = strtof(str.c_str(), &pEnd);
    if (strncmp(pEnd, "\0", 1) != 0 || errno != 0)
    {
        result = 0.0;
        if (ok)
        { *ok = false; }
    }
    else
    {
        if (ok)
        { *ok = true; }
    }
    return result;
}
}
